<!--
 * @Author: licongwei
 * @Date: 2022-03-17 10:49:04
 * @FileDescription: 百度地图
-->
<template>
  <div class="bdmap-wrap">
    <div
      v-show="name"
      class="pop"
      ref="popRef"
      :style="{ left: x + 'px', top: y + 'px' }"
    >
      <ul class="items">
        <li class="item">
          <p class="label">超市名称 :</p>
          <p class="value">{{ shop }}</p>
        </li>
        <li class="item">
          <p class="label">门店名称 :</p>
          <p class="value">{{ name }}</p>
        </li>
        <li class="item">
          <p class="label">推送数据量 :</p>
          <p class="value">{{ value }}条</p>
        </li>
      </ul>
    </div>
    <div class="bd-map" id="bdMap"></div>
  </div>
</template>
<script lang="ts">
import {
  defineComponent,
  onBeforeUnmount,
  watch,
  reactive,
  ref,
  toRefs,
  nextTick
} from 'vue'
import httpRequest from '@/service'
interface IDataState {
  city: string
  point: number[]
  zoom: number
  markers: IMarkerState[]
}
interface IMarkerState {
  shop: string
  shopId: string
  name: string
  nameId: string
  value: number
  position: number[]
  symbol: string
}
interface IPopData {
  x: number
  y: number
  shop: string
  name: string
  value: number
}
export default defineComponent({
  name: 'bdMap',
  props: {
    adcode: {
      type: String,
      default: ''
    },
    shopId: {
      type: String,
      default: ''
    }
  },
  setup(props) {
    let map: any = null
    const bdMapState: IDataState = reactive({
      city: '',
      point: [],
      zoom: 10,
      markers: []
    })
    const getData = (adcode: string) => {
      httpRequest
        .get({ url: 'M3P1BaiduMap', params: { adcode: adcode } })
        .then((res) => {
          bdMapState.city = res.data.city
          bdMapState.point = res.data.point
          bdMapState.zoom = res.data.zoom
          bdMapState.markers = res.data.markers.map((item: any) => ({
            ...item,
            img: item.symbol,
            symbol: item.symbol.slice(item.symbol.indexOf('/images'))
          }))
          map = new BMapGL.Map('bdMap') // 创建Map实例
          init()
        })
        .catch(() => {
          console.log('请求失败')
        })
    }
    getData(props.adcode)

    // 销毁百度地图实例
    onBeforeUnmount(() => {
      map = null
    })
    const popRef = ref<HTMLElement | null>(null)

    const init = () => {
      const point = new BMapGL.Point(bdMapState.point[0], bdMapState.point[1])
      map.centerAndZoom(point, bdMapState.zoom) // 初始化地图,设置中心点坐标和地图级别
      // map.centerAndZoom(bdMapState.city, bdMapState.zoom) // 初始化地图,设置中心点坐标和地图级别
      map.enableScrollWheelZoom(true) //开启鼠标滚轮缩放
      var scaleCtrl = new BMapGL.ScaleControl() // 添加比例尺控件
      map.addControl(scaleCtrl)
      var zoomCtrl = new BMapGL.ZoomControl() // 添加缩放控件
      map.addControl(zoomCtrl)
      map.clearOverlays() //清除地图覆盖物
      mapPolygon()

      // 点击地图区域隐藏弹框
      map.addEventListener('click', function (e: any) {
        if (e.target.id === 'mask') {
          popData.name = ''
        }
      })
      // 拖拽地图区域隐藏弹框
      map.addEventListener('dragstart', function (e: any) {
        if (e.target.id === 'mask') {
          popData.name = ''
        }
      })

      bdMapState.markers.forEach((item: IMarkerState) => {
        if (props.shopId === 'all') {
          mapMarker(item)
        } else {
          if (item.shopId === props.shopId) {
            mapMarker(item)
          }
        }
      })
    }
    const mapPolygon = () => {
      // 创建覆盖区域点
      let bdary = new BMapGL.Boundary()
      bdary.get(bdMapState.city, (rs: any) => {
        let count = rs.boundaries.length //行政区域的点有多少个
        for (let i = 0; i < count; i++) {
          // 地图描点颜色
          let ply = new BMapGL.Polygon(rs.boundaries[i], {
            strokeWeight: 4,
            strokeColor: '#0064FC',
            fillColor: '#DDE7F6'
          })
          ply.id = 'ply'
          map.addOverlay(ply) //添加覆盖物
        }
      })
    }
    // 弹框数据
    let popData: IPopData = reactive({
      x: 0,
      y: 0,
      shop: '',
      name: '',
      value: 0
    })
    const mapMarker = (item: IMarkerState) => {
      let { shopId, nameId, symbol, position } = item
      // 添加描点
      let icon = new BMapGL.Icon(symbol, new BMapGL.Size(25, 30))
      //放入坐标点
      let marker = new BMapGL.Marker(
        new BMapGL.Point(position[0], position[1]),
        { icon: icon }
      )
      marker.id = shopId // 添加id（切换点时控制添加和移除）
      marker.nameId = nameId // 添加nameId（点击时对不同点做区分）
      map.addOverlay(marker)
      marker.addEventListener('click', function (e: any) {
        bdMapState.markers.forEach((item: any) => {
          if (item.nameId === e.target.nameId) {
            popData.shop = item.shop
            popData.name = item.name
            popData.value = item.value
          }
        })
        nextTick(() => {
          const popW = popRef.value?.offsetWidth as number
          const popH = popRef.value?.offsetHeight as number
          popData.x = e.pixel.x + 10
          popData.y = e.pixel.y + 10
          // 判断临界点防止弹框溢出
          if (popData.x > 530) {
            popData.x = popData.x - popW
          }
          if (popData.y > 750) {
            popData.y = popData.y - popH
          }
        })
      })
    }

    // 切换打点
    const changeMarker = (newShopId: string, prevShopId: string) => {
      let allOverlay = map.getOverlays()
      if (newShopId === 'all' && prevShopId !== 'all') {
        // 单选->全选（补充缺少的点）
        bdMapState.markers.forEach((item: IMarkerState) => {
          if (item.shopId !== prevShopId) {
            mapMarker(item)
          }
        })
      } else if (newShopId !== 'all' && prevShopId === 'all') {
        // 全选->单选（移除多余的点）
        allOverlay.forEach((item: any) => {
          if (item.id !== newShopId && item.id !== 'ply') {
            map.removeOverlay(item)
          }
        })
      } else {
        // 单选->单选(删除之前的点再添加新点)
        allOverlay.forEach((item: any) => {
          if (item.id === prevShopId) {
            map.removeOverlay(item)
          }
        })
        bdMapState.markers.forEach((item: IMarkerState) => {
          if (item.shopId === newShopId) {
            mapMarker(item)
          }
        })
      }
    }
    watch(
      () => props.shopId,
      (newVal, prevVal) => {
        changeMarker(newVal, prevVal)
      }
    )
    return {
      popRef,
      ...toRefs(popData)
    }
  }
})
</script>
<style lang="less" scoped>
.bdmap-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  .pop {
    position: absolute;
    padding: 24px;
    z-index: 1000;
    white-space: nowrap;
    background-color: rgba(0, 71, 157, 0.9);
    border-radius: 5px;
    box-shadow: 0 0 30px 10px rgba(0, 71, 157, 0.5);
    ul.items {
      width: 100%;
      margin-right: 24px;
      li.item {
        line-height: 40px;
        display: flex;
        flex-wrap: nowrap;
        .label {
          flex: 0 0 100px;
          font-size: 16px;
          color: #e8effb;
        }
        .value {
          flex: 1;
          font-size: 16px;
          color: #00ffea;
          font-family: 'AliHYAiHei';
          white-space: nowrap;
        }
      }
    }
  }
  .bd-map {
    position: relative;
    height: 100%;
  }
}
</style>
